package com.yjc.controller;

import com.yjc.entity.Result;
import com.yjc.manager.holder.ClassHolder;
import com.yjc.spring.boot.context.DynamicLoadSpringContext;
import com.yjc.spring.boot.yaml.YamlConfigFactory;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

/**
 * 加载、卸载jar包
 *
 * @author 闫佳成
 * @version: 1.0
 * @since 2024/10/10 16:19
 */
@RequestMapping("jar")
@RestController
public class FileClassController {
    private final ClassHolder classHolder = ClassHolder.getInstance();

    @GetMapping("load")
    public Result load(String file){
        try {
            classHolder.loadClassByFile(YamlConfigFactory.getConcumerYamlConfig().getPathName(), file);
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) DynamicLoadSpringContext.getInstance().getContext();
            //将加载的类注入到spring
            Map<String, Map<Class<?>, Class<?>>> jarInterfaceMap = classHolder.getJarInterfaceMap();
            Map<Class<?>, Class<?>> interfaceClassMap = jarInterfaceMap.get(file);
            for (Map.Entry<Class<?>, Class<?>> interfaceClassEntry : interfaceClassMap.entrySet()) {
                Class<?> interfaceClass = interfaceClassEntry.getKey();
                Class<?> clazz = interfaceClassEntry.getValue();
                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
                AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
                String beanName = getBeanName(file, interfaceClass);
                beanFactory.registerBeanDefinition(beanName,beanDefinition);
                beanFactory.autowireBean(clazz);
                beanFactory.initializeBean(clazz,beanName);
                beanFactory.clearMetadataCache();
            }
        }catch (Exception e){
            e.printStackTrace();
            return new Result(e.getMessage());
        }
        return new Result("ok");
    }

    @GetMapping("unload")
    public Result unload(String file){
        try {
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) DynamicLoadSpringContext.getInstance().getContext();
            Map<String, Map<Class<?>, Class<?>>> jarInterfaceMap = classHolder.getJarInterfaceMap();
            Map<Class<?>, Class<?>> interfaceClassMap = jarInterfaceMap.get(file);
            if (MapUtils.isNotEmpty(interfaceClassMap)){;
                for (Map.Entry<Class<?>, Class<?>> interfaceClassEntry : interfaceClassMap.entrySet()) {
                    Class<?> interfaceClass = interfaceClassEntry.getKey();
                    String beanName = getBeanName(file, interfaceClass);
                    Object bean = beanFactory.getBean(beanName);
                    beanFactory.destroyBean(beanName,bean);
                    beanFactory.removeBeanDefinition(beanName);
                }
                classHolder.unload(file);
            }
        }catch (Exception e){
            e.printStackTrace();
            return new Result(e.getMessage());
        }
        return new Result("ok");
    }

    private String getBeanName(String jarName,Class<?> interfaceClass){
        return jarName + "." + interfaceClass.getName();
    }
}
